/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.annotation;

import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.InjectionPoint;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.beans.factory.support.LookupOverride;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

/**
 * {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}
 * implementation that autowires annotated fields, setter methods, and arbitrary
 * config methods. Such members to be injected are detected through annotations:
 * by default, Spring's {@link Autowired @Autowired} and {@link Value @Value}
 * annotations.
 *
 * <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
 * if available, as a direct alternative to Spring's own {@code @Autowired}.
 *
 * <h3>Autowired Constructors</h3>
 * <p>Only one constructor of any given bean class may declare this annotation with
 * the 'required' attribute set to {@code true}, indicating <i>the</i> constructor
 * to autowire when used as a Spring bean. Furthermore, if the 'required' attribute
 * is set to {@code true}, only a single constructor may be annotated with
 * {@code @Autowired}. If multiple <i>non-required</i> constructors declare the
 * annotation, they will be considered as candidates for autowiring. The constructor
 * with the greatest number of dependencies that can be satisfied by matching beans
 * in the Spring container will be chosen. If none of the candidates can be satisfied,
 * then a primary/default constructor (if present) will be used. If a class only
 * declares a single constructor to begin with, it will always be used, even if not
 * annotated. An annotated constructor does not have to be public.
 *
 * <h3>Autowired Fields</h3>
 * <p>Fields are injected right after construction of a bean, before any
 * config methods are invoked. Such a config field does not have to be public.
 *
 * <h3>Autowired Methods</h3>
 * <p>Config methods may have an arbitrary name and any number of arguments; each of
 * those arguments will be autowired with a matching bean in the Spring container.
 * Bean property setter methods are effectively just a special case of such a
 * general config method. Config methods do not have to be public.
 *
 * <h3>Annotation Config vs. XML Config</h3>
 * <p>A default {@code AutowiredAnnotationBeanPostProcessor} will be registered
 * by the "context:annotation-config" and "context:component-scan" XML tags.
 * Remove or turn off the default annotation configuration there if you intend
 * to specify a custom {@code AutowiredAnnotationBeanPostProcessor} bean definition.
 *
 * <p><b>NOTE:</b> Annotation injection will be performed <i>before</i> XML injection;
 * thus the latter configuration will override the former for properties wired through
 * both approaches.
 *
 * <h3>{@literal @}Lookup Methods</h3>
 * <p>In addition to regular injection points as discussed above, this post-processor
 * also handles Spring's {@link Lookup @Lookup} annotation which identifies lookup
 * methods to be replaced by the container at runtime. This is essentially a type-safe
 * version of {@code getBean(Class, args)} and {@code getBean(String, args)}.
 * See {@link Lookup @Lookup's javadoc} for details.
 *
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @author Stephane Nicoll
 * @author Sebastien Deleuze
 * @author Sam Brannen
 * @since 2.5
 * @see #setAutowiredAnnotationType
 * @see Autowired
 * @see Value
 */
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
		implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {

	protected final Log logger = LogFactory.getLog(getClass());

	private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);

	private String requiredParameterName = "required";

	private boolean requiredParameterValue = true;

	private int order = Ordered.LOWEST_PRECEDENCE - 2;

	@Nullable
	private ConfigurableListableBeanFactory beanFactory;

	private final Set<String> lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));

	private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);

	private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256);


	/**
	 * Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
	 * standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
	 * <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
	 * if available.
	 */
	@SuppressWarnings("unchecked")
	public AutowiredAnnotationBeanPostProcessor() {
		this.autowiredAnnotationTypes.add(Autowired.class);
		this.autowiredAnnotationTypes.add(Value.class);
		try {
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}


	/**
	 * Set the 'autowired' annotation type, to be used on constructors, fields,
	 * setter methods, and arbitrary config methods.
	 * <p>The default autowired annotation types are the Spring-provided
	 * {@link Autowired @Autowired} and {@link Value @Value} annotations as well
	 * as JSR-330's {@link javax.inject.Inject @Inject} annotation, if available.
	 * <p>This setter property exists so that developers can provide their own
	 * (non-Spring-specific) annotation type to indicate that a member is supposed
	 * to be autowired.
	 */
	public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) {
		Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
		this.autowiredAnnotationTypes.clear();
		this.autowiredAnnotationTypes.add(autowiredAnnotationType);
	}

	/**
	 * Set the 'autowired' annotation types, to be used on constructors, fields,
	 * setter methods, and arbitrary config methods.
	 * <p>The default autowired annotation types are the Spring-provided
	 * {@link Autowired @Autowired} and {@link Value @Value} annotations as well
	 * as JSR-330's {@link javax.inject.Inject @Inject} annotation, if available.
	 * <p>This setter property exists so that developers can provide their own
	 * (non-Spring-specific) annotation types to indicate that a member is supposed
	 * to be autowired.
	 */
	public void setAutowiredAnnotationTypes(Set<Class<? extends Annotation>> autowiredAnnotationTypes) {
		Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
		this.autowiredAnnotationTypes.clear();
		this.autowiredAnnotationTypes.addAll(autowiredAnnotationTypes);
	}

	/**
	 * Set the name of an attribute of the annotation that specifies whether it is required.
	 * @see #setRequiredParameterValue(boolean)
	 */
	public void setRequiredParameterName(String requiredParameterName) {
		this.requiredParameterName = requiredParameterName;
	}

	/**
	 * Set the boolean value that marks a dependency as required.
	 * <p>For example if using 'required=true' (the default), this value should be
	 * {@code true}; but if using 'optional=false', this value should be {@code false}.
	 * @see #setRequiredParameterName(String)
	 */
	public void setRequiredParameterValue(boolean requiredParameterValue) {
		this.requiredParameterValue = requiredParameterValue;
	}

	public void setOrder(int order) {
		this.order = order;
	}

	@Override
	public int getOrder() {
		return this.order;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
			throw new IllegalArgumentException(
					"AutowiredAnnotationBeanPostProcessor requires a ConfigurableListableBeanFactory: " + beanFactory);
		}
		this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
	}


	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		//找到所有的注入点@AutoWired
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

	@Override
	public void resetBeanDefinition(String beanName) {
		this.lookupMethodsChecked.remove(beanName);
		this.injectionMetadataCache.remove(beanName);
	}

	@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
			throws BeanCreationException {

		// Let's check for lookup methods here...
		//这个是Lockup的逻辑，现在这里暂时不用管
		if (!this.lookupMethodsChecked.contains(beanName)) {
			if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
				try {
					Class<?> targetClass = beanClass;
					do {
						ReflectionUtils.doWithLocalMethods(targetClass, method -> {
							Lookup lookup = method.getAnnotation(Lookup.class);
							if (lookup != null) {
								Assert.state(this.beanFactory != null, "No BeanFactory available");
								LookupOverride override = new LookupOverride(method, lookup.value());
								try {
									RootBeanDefinition mbd = (RootBeanDefinition)
											this.beanFactory.getMergedBeanDefinition(beanName);
									mbd.getMethodOverrides().addOverride(override);
								}
								catch (NoSuchBeanDefinitionException ex) {
									throw new BeanCreationException(beanName,
											"Cannot apply @Lookup to beans without corresponding bean definition");
								}
							}
						});
						targetClass = targetClass.getSuperclass();
					}
					while (targetClass != null && targetClass != Object.class);

				}
				catch (IllegalStateException ex) {
					throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
				}
			}
			this.lookupMethodsChecked.add(beanName);
		}

		// Quick check on the concurrent map first, with minimal locking.
		//决定一组构造方法的逻辑代码，candidateConstructorsCache是一个构造方法候选者的集合，就是说如果找到了符合条件的构造方法
		//都会缓存到这个集合中，表示是符合条件的构造方法的候选者集合
		//这里先从缓存中去取,如果缓存中没有，就去推断出符合的记录添加到缓存中
		Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
		if (candidateConstructors == null) {
			// Fully synchronized resolution now...
			synchronized (this.candidateConstructorsCache) {
				//先从缓存中去取，如果有，就直接返回了，如果没有，就去找
				candidateConstructors = this.candidateConstructorsCache.get(beanClass);
				if (candidateConstructors == null) {
					Constructor<?>[] rawCandidates;
					try {
						//这个是得到一个Bean中的声明的所有的构造方法列表，是一个数组，数组里面是bean中的所有构造方法
						rawCandidates = beanClass.getDeclaredConstructors();
					}
					catch (Throwable ex) {
						throw new BeanCreationException(beanName,
								"Resolution of declared constructors on bean Class [" + beanClass.getName() +
								"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
					}
					//构建一个候选者列表的构造方法集合
					List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
					//表示一个加了@AutoWired注解并且require=true的构造方法
					Constructor<?> requiredConstructor = null;
					//表示是一个默认的构造方法，是一个空参数的构造方法
					Constructor<?> defaultConstructor = null;
					//这个不太清楚
					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
					int nonSyntheticConstructors = 0;
					//循环上面得到的构造方法列表
					for (Constructor<?> candidate : rawCandidates) {
						if (!candidate.isSynthetic()) {
							nonSyntheticConstructors++;
						}
						else if (primaryConstructor != null) {
							continue;
						}
						//根据当前循环的构造方法，看是否实现了@AutoWired注解，如果没有，就去找到父类，看父类是否有
						MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
						if (ann == null) {
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							if (userClass != beanClass) {
								try {
									Constructor<?> superCtor =
											userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);
								}
								catch (NoSuchMethodException ex) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						//如果找到了@AutoWired 注解的构造方法，然后进入逻辑判断
						if (ann != null) {
							//requiredConstructor表示是加了@AutoWied注解的并且required=true的构造方法
							//也就是如果在前面的循环中已经找到了这个方法，代码逻辑还进入了这里，表示前面已经找到了
							//要使用的构造方法，这里直接报错，也就是说在bean中的构造方法，不能对一个以上的构造方法加@autoWired注解(包含required有true的情况）
							if (requiredConstructor != null) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}
							//得到@AutoWired注解上的required属性
							boolean required = determineRequiredStatus(ann);
							if (required) {
								//如果required属性为true，那么设置requiredConstructor为当前找到的一个要使用的构造方法
								//如果说前面的循环已经找到了@AutoWired的构造，那么这里又找到了@AutoWired的构造，不管required是否为true都会报错
								//也就说一个bean中只能有一个@AutoWired=true的构造方法，并且再加入了@AutoWried=false也要报错
								if (!candidates.isEmpty()) {
									throw new BeanCreationException(beanName,
											"Invalid autowire-marked constructors: " + candidates +
											". Found constructor with 'required' Autowired annotation: " +
											candidate);
								}
								requiredConstructor = candidate;
							}
							//最后加入候选者列表中，就算是@AutoWired中的设置的属性required为false也加入候选者列表中
							candidates.add(candidate);
						}
						//当前循环的构造方法的参数为0的话，表示是默认的构造方法，默认的构造方法赋值给默认构造方法变量
						else if (candidate.getParameterCount() == 0) {
							defaultConstructor = candidate;
						}
					}
					if (!candidates.isEmpty()) {
						// Add default constructor to list of optional constructors, as fallback.
						//如果说required为true的构造方法没有找到，如果找到了默认的构造方法也加入候选者列表中
						if (requiredConstructor == null) {
							if (defaultConstructor != null) {
								candidates.add(defaultConstructor);
							}
							else if (candidates.size() == 1 && logger.isInfoEnabled()) {
								logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
										"': single autowire-marked constructor flagged as optional - " +
										"this constructor is effectively required since there is no " +
										"default constructor to fall back to: " + candidates.get(0));
							}
						}
						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
					}
					//这里的判断是说如果说我们前面循环前找到的所有构造方法只有一个，并且这个构造的参数是大于0的，那么就直接使用这个构造
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
						candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
					}
					else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
							defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
					}
					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor};
					}
					else {
						candidateConstructors = new Constructor<?>[0];
					}
					//将找到的@AutoWired构造方法放入缓存
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}

		/**
		 * 总结下上面的过程：
		 * 1.找到bean中的所有构造方法
		 * 2.循环每个构造方法，如果是实现了@AutoWired的就加入到候选candidates集合中；
		 * 3.如果说找到了两个@AutoWired的方法，那么就报错；
		 * 4.如果说构造方法中有@AutoWired的，但是也找到了一个默认的无参数构造，那么也加入到candidates，但是这个时候只有@AutoWired中的required为false才会加入，也就是说如果
		 * 找到了一个默认无参数构造，一个@AutoWired=true的构造，那么这个默认的无参数构造就会被舍弃，只有找到的@AutoWired=false，那么又找到了一个无参数构造，
		 * 才会加入到candidates中,也就是说如果找到了@AutoWired=false的构造和一般的无参数构造一样，都加入到了后续列表中，spring把它当成了一个不确定的因素，需要后续继续推导；
		 * 5.如果说找到的构造方法只有一个，并且这个构造方法的参数是大于0的，那么就返回这个构造方法；
		 * 6.如果前三个都不能满足，也就说是bean中存在2个以上的构造方法，但是都没有加@AutoWired注解的构造，那么直接返回null；
		 */
		return (candidateConstructors.length > 0 ? candidateConstructors : null);
	}

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		//在实例化过后调用的后置处理器先将注入点找到并且准入到了缓存injectionMetadataCache中了
		//所以这里的就是从缓存中获取，当然了如果在前面的后置处理器中没有注入成功，那么这个也会去注入，一般不会出现这种情况
		//metadata就是bean类的所有注入点，只包括两种：普通非静态方法的注入点和非静态属性的注入点
		//这里的注入点有两个，属性和犯法，所以下面的调用也分为两种
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			//开始注入，这里的注入根据是属性和方法调用不同的注入方式
			//AutowiredFieldElement属性的注入
			//AutowiredMethodElement是方法的注入
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}

	@Deprecated
	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {

		return postProcessProperties(pvs, bean, beanName);
	}

	/**
	 * 'Native' processing method for direct calls with an arbitrary target instance,
	 * resolving all of its fields and methods which are annotated with one of the
	 * configured 'autowired' annotation types.
	 * @param bean the target instance to process
	 * @throws BeanCreationException if autowiring failed
	 * @see #setAutowiredAnnotationTypes(Set)
	 */
	public void processInjection(Object bean) throws BeanCreationException {
		Class<?> clazz = bean.getClass();
		InjectionMetadata metadata = findAutowiringMetadata(clazz.getName(), clazz, null);
		try {
			metadata.inject(bean, null, null);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					"Injection of autowired dependencies failed for class [" + clazz + "]", ex);
		}
	}

	/**
	 * 找到所有的依赖注入点，注入点包括@AutoWired @Value @Inject
	 * @param beanName
	 * @param clazz
	 * @param pvs
	 * @return
	 */

	private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Quick check on the concurrent map first, with minimal locking.
		/**
		 * 先从缓存中获取，如果缓存中没有，就去根据bean的类去找到，找到过后注入到injectionMetadataCache缓存中
		 * 我们知道@AutoWired注入可以通过属性、普通方法、构造进行注入，这里对属性和普通方法进行注入
		 */
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
					//如果metadata不为空，则去找注入点，如果注入点为空那么metadata=InjectionMetadata.EMPTY
					metadata = buildAutowiringMetadata(clazz);
					//找到过后放入缓存
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		//注意，这里不是判断clzz是否实现了@AutoWired,@Value @Inject注解，这里的判断很简单
		//1.你传入的clazz如果是java.开头的则证明是java的内置的类，那么就返回false
		//2.你传入的autowiredAnnotationTypes是否是java开头的注解
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		/**
		 * 下面用了一个do while循环去找注入点，
		 * 这里需要注意的是为什么要用do while，很简单的例子就是比如一个UserServce加了一个注解，那么是继承了BaseService
		 * 而BaseService中没有加@Componet，但是UserService加了@Component注解，那么这个时候以UserService为bean去找注入点
		 * spring会找到他的父类，一级一级的往上找，直到找到最顶层的类，所以在父类中加了@AutoWired等注解，就算父类没有@Component
		 * 也是可以找到摈弃注入的
		 * 下面的循环中是分了两部分来找的，第一部分是属性的注入，第二部分是普通方法的注入，而构造方法的注入不在这里
		 */
		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

			//属性的注入点寻找,下面使用的是java8的lambad表达式的方式，这里不关心，关心的是lambad里面的逻辑
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
                //循环每个属性，看下属性是否实现了@AutoWired,@Value @Inject注解,如果没有实现，那么就会返回null
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
					//spring规定的是静态属性不能注入，也就是说你写的private static UserSerivce userService;
                     //是不能注入的
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					//这里读取的是@AutoWired上面的required,这个属性默认是true，sping这里的意思就是说
//					//如果你配置了required属性，如果这个属性为false，那么在注入的过程中如果没有找到，注入失败了，那么就不会报错
//					//如果设置为true，那么如果没有注入成功，会报异常
					boolean required = determineRequiredStatus(ann);
					//找到过后然后放入currElements缓存，这里的放入的对象是AutowiredFieldElement，就是针对属性的注入
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			//下面的这个方法是针对普通方法注入的处理
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				//这里也是去判断普通注入的方法是否有@AutoWired,@Value @Inject注解
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				//如果方法有注解，并且方法是合法的，那么就进入找寻普通方法注入点的逻辑
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					//相同的是注入的方法不能是静态方法
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					//方法的参数也不能是空，因为@AutoWired方法的注入是通过方法的参数类型进行注入的
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					//和属性注入的逻辑一样
					boolean required = determineRequiredStatus(ann);
					//在这里将方法生成一个属性描述器，这里面判断了是写入方法还是读取方法
//					这里的没隔方法的一些细节逻辑封装的有点多，我在这里大部分是为了把spirng的大部分逻辑和思想得到
					//所以一些特别处理的地方就没有去细看，有兴趣的可以去细看下，比如下面这行代码是如何处理的
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					//封装好了AutowiredMethodElement，然后放入缓存
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			//每次循环找到注入点注入到currElements后，加入到elements
			elements.addAll(0, currElements);
			//每次本类找到过后，然后获取父类，一级一级的往上找
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);
      //这里将找到的注入点elements封装成一个InjectionMetadata返回，如果elements=null，那么封装的是InjectionMetadata.EMPTY
		return InjectionMetadata.forElements(elements, clazz);
	}

	@Nullable
	private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
		MergedAnnotations annotations = MergedAnnotations.from(ao);
		for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
			MergedAnnotation<?> annotation = annotations.get(type);
			if (annotation.isPresent()) {
				return annotation;
			}
		}
		return null;
	}

	/**
	 * Determine if the annotated field or method requires its dependency.
	 * <p>A 'required' dependency means that autowiring should fail when no beans
	 * are found. Otherwise, the autowiring process will simply bypass the field
	 * or method when no beans are found.
	 * @param ann the Autowired annotation
	 * @return whether the annotation indicates that a dependency is required
	 */
	@SuppressWarnings({"deprecation", "cast"})
	protected boolean determineRequiredStatus(MergedAnnotation<?> ann) {
		// The following (AnnotationAttributes) cast is required on JDK 9+.
		return determineRequiredStatus((AnnotationAttributes)
				ann.asMap(mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType())));
	}

	/**
	 * Determine if the annotated field or method requires its dependency.
	 * <p>A 'required' dependency means that autowiring should fail when no beans
	 * are found. Otherwise, the autowiring process will simply bypass the field
	 * or method when no beans are found.
	 * @param ann the Autowired annotation
	 * @return whether the annotation indicates that a dependency is required
	 * @deprecated since 5.2, in favor of {@link #determineRequiredStatus(MergedAnnotation)}
	 */
	@Deprecated
	protected boolean determineRequiredStatus(AnnotationAttributes ann) {
		return (!ann.containsKey(this.requiredParameterName) ||
				this.requiredParameterValue == ann.getBoolean(this.requiredParameterName));
	}

	/**
	 * Obtain all beans of the given type as autowire candidates.
	 * @param type the type of the bean
	 * @return the target beans, or an empty Collection if no bean of this type is found
	 * @throws BeansException if bean retrieval failed
	 */
	protected <T> Map<String, T> findAutowireCandidates(Class<T> type) throws BeansException {
		if (this.beanFactory == null) {
			throw new IllegalStateException("No BeanFactory configured - " +
					"override the getBeanOfType method or specify the 'beanFactory' property");
		}
		return BeanFactoryUtils.beansOfTypeIncludingAncestors(this.beanFactory, type);
	}

	/**
	 * Register the specified bean as dependent on the autowired beans.
	 */
	private void registerDependentBeans(@Nullable String beanName, Set<String> autowiredBeanNames) {
		if (beanName != null) {
			for (String autowiredBeanName : autowiredBeanNames) {
				if (this.beanFactory != null && this.beanFactory.containsBean(autowiredBeanName)) {
					this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Autowiring by type from bean name '" + beanName +
							"' to bean named '" + autowiredBeanName + "'");
				}
			}
		}
	}

	/**
	 * Resolve the specified cached method argument or field value.
	 */
	@Nullable
	private Object resolvedCachedArgument(@Nullable String beanName, @Nullable Object cachedArgument) {
		if (cachedArgument instanceof DependencyDescriptor) {
			DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
			Assert.state(this.beanFactory != null, "No BeanFactory available");
			return this.beanFactory.resolveDependency(descriptor, beanName, null, null);
		}
		else {
			return cachedArgument;
		}
	}


	/**
	 * Class representing injection information about an annotated field.
	 */
	private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {

		private final boolean required;

		private volatile boolean cached = false;

		@Nullable
		private volatile Object cachedFieldValue;

		public AutowiredFieldElement(Field field, boolean required) {
			super(field, null);
			this.required = required;
		}

		/**
		 * 这里就是根据属性注入的逻辑
		 * @param bean
		 * @param beanName
		 * @param pvs
		 * @throws Throwable
		 */
		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			//这里判断是否有缓存，cached默认是false，当field第一次加载的时候是没有缓存的，当加载过后会放入缓存cachedFieldValue
			//cachedFieldValue也是一个依赖描述器，具体为ShortcutDependencyDescriptor，可以理解为较块的方式获取bean对象
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
//				和xml那边一模一样的，就是先通过属性来构造一个依赖描述器,就是封装了field的所有属性
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				//设置依赖描述器的容器的bean class
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
					//然后通过依赖描述器来找到一个bean，请注意，这里是属性的依赖注入，比如private UserService uservice
//					//那么这里是来找到bean类下面的属性UserService在spring容器中的ben对象，也就是value
					//resolveDependency在这里是先byType，再byName，当byType有多个的时候，就要进行byName,所以在
//					//在spring中写注入@AutoWired对应的属性名称的时候尽量规范一点
					/**
					 * 下面这个方法有点复杂，简单来说我们都知道它在干嘛，无非就是根据依赖描述器（字段信息）去容器获取一个bean对象
					 * desc：被注入对象的字段描述信息
					 * beanName：当前注入属性或者方法所在的bean对象的beanName
					 * autowiredBeanNames：被注入对象所在的beanName集合（比如某个bean中 写private UserService userService, 如果beanName
					 * =userService，那么autowiredBeanNames中就会存入userService这个名字）
					 * typeConverter：转换器，如果发现注入的是一个@Value（“xxx”），那么这个xxx是否有转换器进行转换
					 * 在这个方法里面的逻辑我大概罗列一下 ：
					 * 1.处理@Value注解，如果@Value有值，那么就会直接获取@Value的值，这个时候如果是占位符$，那么会从环境中Envirment
					 * 中获取一个对应的属性值注入，如果是#el表达式，那么会从spring容器中获取一个bean返回;
					 * 3.注入的类型是否是Map Collection Array，如果是就获取bean封装成Map or  Collection or Array返回
					 * 2.然后会去容器中获取bean，如果获取的bean是一个，那么封装了直接返回，如果多个bean，这个时候就要进行处理：
					 *  a.先筛选，通过是否是自动注入候选者筛选，然后在看是否有泛型，有的话对泛型的类型是否满足根据注入类型从容器中获取的类型进行判断；
					 *  b.然后在判断@Qualifier,看是否有满足的@Qualifier名字匹配的bean，有的话过滤非@Qualifier配置的名字的bean；					 *
					 *  a.看是否有@Primary注解，如果有，那么就选择具有@PrimaryKey注解所在的bean，注意的是相同的Bean不能同时存在@PrimaryKey注解
					 *  b.如果没有再看有没有Priority优先级的，如果有优先级的注解，那么判断优先级的大小
					 *  优先级的数字越小，级别越高
					 *  c.如果还是不能确定就开始byName
					 *
					 *
					 */
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}

				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				//下面的逻辑是如果开启了缓存cached，默认是false，然后取出注入的属性名称，也就是beanName，然后判断，设置缓存字段值
				synchronized (this) {
					if (!this.cached) {
						if (value != null || this.required) {
							this.cachedFieldValue = desc;
							registerDependentBeans(beanName, autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName) &&
										beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
									this.cachedFieldValue = new ShortcutDependencyDescriptor(
											desc, autowiredBeanName, field.getType());
								}
							}
						}
						else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
			if (value != null) {
				//如果找到了注入的bena，然后通过反射进行注入
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}
	}


	/**
	 * Class representing injection information about an annotated method.
	 */
		private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {

		private final boolean required;

		private volatile boolean cached = false;

		@Nullable
		private volatile Object[] cachedMethodArguments;

		public AutowiredMethodElement(Method method, boolean required, @Nullable PropertyDescriptor pd) {
			super(method, pd);
			this.required = required;
		}

		/**
		 * 方法的注入，方法注入的要点是：
		 * 1.方法必须是普通的非静态方法（非构造方法，构造方法不在此处处理）
		 * 2.方法的参数个数必须大于0，也就是至少为1个
		 * 3.然后根据前两个条件，然后循环每一个方法的参数，请注意，每个参数应该都是一个bean对象，
		 * 然后封装一个参数数组，最后通过反射调用方法进行注入
		 * spring代码写的很多，但是我们研究spring的源码要看关键部分，关键部分就是它如何进行依赖注入的
		 * 通过属性和普通方法，至于一些很细的细节，就算你现在弄清楚了，过一段时间也会忘，所以太细的如果不太理解，就飘过
		 * @param bean
		 * @param beanName
		 * @param pvs
		 * @throws Throwable
		 */

		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			if (checkPropertySkipping(pvs)) {
				return;
			}
//			方法的注入，member强制转换成一个Method
			Method method = (Method) this.member;
			Object[] arguments;
			if (this.cached) {
				// Shortcut for avoiding synchronization...
				arguments = resolveCachedArguments(beanName);
			}
			else {
				//得到方法参数的个数，并且封装一个Object arguments
				int argumentCount = method.getParameterCount();
//				//这个数组存放的是每个参数对应的bean在spring容器中的bean对象
				arguments = new Object[argumentCount];
				//这里存放的是每个参数对应在spring容器中的bean对象构建的依赖描述器
				DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
				Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				//下面的代码逻辑就是循环每个方法参数，然后从spring容器中获取bean，然后填充到arguments中
//				逻辑都和属性注入一样，通过依赖描述器调用resolveDependency来获取一个bean对象
				for (int i = 0; i < arguments.length; i++) {
					MethodParameter methodParam = new MethodParameter(method, i);
					DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
					currDesc.setContainingClass(bean.getClass());
					descriptors[i] = currDesc;
					try {
						Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
						if (arg == null && !this.required) {
							arguments = null;
							break;
						}
						arguments[i] = arg;
					}
					catch (BeansException ex) {
						throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
					}
				}
				synchronized (this) {
					if (!this.cached) {
						if (arguments != null) {
							DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
							registerDependentBeans(beanName, autowiredBeans);
							if (autowiredBeans.size() == argumentCount) {
								Iterator<String> it = autowiredBeans.iterator();
								Class<?>[] paramTypes = method.getParameterTypes();
								for (int i = 0; i < paramTypes.length; i++) {
									String autowiredBeanName = it.next();
									if (beanFactory.containsBean(autowiredBeanName) &&
											beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
										cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
												descriptors[i], autowiredBeanName, paramTypes[i]);
									}
								}
							}
							this.cachedMethodArguments = cachedMethodArguments;
						}
						else {
							this.cachedMethodArguments = null;
						}
						this.cached = true;
					}
				}
			}
			if (arguments != null) {
				try {
					//然后进行调用，就类似于setXxx(UserService u1,UsereSerivce u2),两个参数就是argumentgs
					//arguments就是上面循环从spring容器中获取的
					ReflectionUtils.makeAccessible(method);
					method.invoke(bean, arguments);
				}
				catch (InvocationTargetException ex) {
					throw ex.getTargetException();
				}
			}
		}

		@Nullable
		private Object[] resolveCachedArguments(@Nullable String beanName) {
			Object[] cachedMethodArguments = this.cachedMethodArguments;
			if (cachedMethodArguments == null) {
				return null;
			}
			Object[] arguments = new Object[cachedMethodArguments.length];
			for (int i = 0; i < arguments.length; i++) {
				arguments[i] = resolvedCachedArgument(beanName, cachedMethodArguments[i]);
			}
			return arguments;
		}
	}


	/**
	 * DependencyDescriptor variant with a pre-resolved target bean name.
	 */
	@SuppressWarnings("serial")
	/**
	 * 这个依赖描述器简单来说就是spring每次从容器中读取了一个bean对象过后，它开启了缓存，会把获取的beanname封装到
	 * 这里，然后下次来获取的时候，如果发现有缓存，那么就会从这里去获取bean，也就是每一个filed注入都会有一个ShortcutDependencyDescriptor
	 * 如果下次还是这个field注入，那么就胡简单的从缓存中读取
	 */
	private static class ShortcutDependencyDescriptor extends DependencyDescriptor {

		private final String shortcut;

		private final Class<?> requiredType;

		public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut, Class<?> requiredType) {
			super(original);
			this.shortcut = shortcut;//指的就是beanName
			this.requiredType = requiredType;
		}

		@Override
		public Object resolveShortcut(BeanFactory beanFactory) {
			return beanFactory.getBean(this.shortcut, this.requiredType);
		}
	}

}
